#include "mqtt_app.h"
#include <iostream>
#include <memory>
#include "config.h"
#include "zlog_app.h"
#include <thread>
#include <atomic>
#include <vector>
#include "tcp_server.h"
#include <csignal>
#include "linenoise_app.h"
#include "dev_data.h"
#include "up_treaty.h"
#include "ThreadSafeQueue.h"
#include "modbus_rtu.h"
using namespace std;
static std::shared_ptr<zlog_app> p_zlog_app;
static std::shared_ptr<app_config> sp_cfg;
static std::shared_ptr<dev_data> s_dev_data;
static std::shared_ptr<up_treaty> s_up_treaty;
static std::shared_ptr<SingleClientTcpServer> s_tcp_server;
static std::shared_ptr<ThreadSafeQueue<EVENT>> s_send_down_queue;      // 下行数据队列,用于存储待发送的下行事件
static std::shared_ptr<ThreadSafeQueue<EVENT>> s_send_up_queue;        // 上行数据队列,用于存储待发送的上行事件
static std::shared_ptr<ThreadSafeQueue<EVENT>> s_send_modbusrtu_queue; // 上行数据队列,用于存储待发送的上行事件
static std::shared_ptr<dev_flags> s_app_status_flag;
static std::shared_ptr<modbus_rtu> s_app_modbus_rtu;
// 全局停止标志
static atomic<bool> g_shouldStop(false);

std::shared_ptr<app_config> get_app_config_ptr()
{
    return sp_cfg;
}
std::shared_ptr<dev_data> get_dev_data_ptr()
{
    return s_dev_data;
}
std::shared_ptr<up_treaty> get_up_treaty_ptr()
{
    return s_up_treaty;
}
std::shared_ptr<SingleClientTcpServer> get_tcp_server_ptr()
{
    return s_tcp_server;
}
std::shared_ptr<ThreadSafeQueue<EVENT>> get_send_down_queue_ptr()
{
    assert(s_send_down_queue);
    return s_send_down_queue;
}
std::shared_ptr<ThreadSafeQueue<EVENT>> get_send_up_queue_ptr()
{
    assert(s_send_up_queue);
    return s_send_up_queue;
}
std::shared_ptr<ThreadSafeQueue<EVENT>> get_send_modbusrtu_queue_ptr()
{
    assert(s_send_modbusrtu_queue);
    return s_send_modbusrtu_queue;
}
std::shared_ptr<struct dev_flags> get_app_status_flag_ptr()
{
    assert(s_app_status_flag);
    return s_app_status_flag;
}
// void set_matt_stop_flag(void);
void handleSignal(int signal)
{
    g_shouldStop = true;
    // set_stop_flag(g_shouldStop);
    set_linenoise_stop_flag(g_shouldStop);
    set_mqtt_stop_flag(g_shouldStop);
    s_app_modbus_rtu->set_stop_rtu_thread();
    zlog_info(p_zlog_app->get_category_all(), "Received signal %d, shutting down gracefully...", signal);
}

int main(int argc, char *argv[])
{
    cout << "hello 58 dtu version : " << __DATE__ << "  " << __TIME__ << endl;
    // 设置信号处理
    signal(SIGINT, handleSignal);
    signal(SIGTERM, handleSignal);

    p_zlog_app = std::make_shared<zlog_app>();
    s_dev_data = make_shared<dev_data>();
    sp_cfg = std::make_shared<app_config>(p_zlog_app);
    s_up_treaty = make_shared<up_treaty>();
    s_send_down_queue = make_shared<ThreadSafeQueue<EVENT>>();      // 上行数据处理类
    s_send_up_queue = make_shared<ThreadSafeQueue<EVENT>>();        // 下行数据处理类
    s_send_modbusrtu_queue = make_shared<ThreadSafeQueue<EVENT>>(); // modbus rtu
    s_app_status_flag = make_shared<dev_flags>();                   // 状态标志
    s_app_modbus_rtu = make_shared<modbus_rtu>();

    if (!sp_cfg->acquire_lock())
    {
        cout << "lock failed........." << endl;
        exit(1);
    }
    if (!sp_cfg->load_config_from_file())
    {
        sp_cfg->default_config();
        sp_cfg->save_config_to_file();
    }
    sp_cfg->print_config();

    std::vector<uint8_t> vec_recv_data;
    auto onData = [&](std::vector<uint8_t> &data)
    {
        s_up_treaty->classfy_parse_frame(data, vec_recv_data);
        if (vec_recv_data.size())
        {
            s_tcp_server->sendData(vec_recv_data);
        }
        data.clear();
        vec_recv_data.clear();
    };
    s_tcp_server = make_shared<SingleClientTcpServer>(get_app_config_ptr()->cfg.bind_port, onData);
    s_tcp_server->start();

    int mqtt_init(void);
    mqtt_init();

    // 等待停止信号
    while (!g_shouldStop.load())
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    // linenoise_run();

    // wait tcp server stop
    s_tcp_server->stop();
    sp_cfg->release_lock();
    s_app_modbus_rtu->wait_rtu_thread_stop();

    sleep(1);
    zlog_fini();
    printf("zlog fini success\n");

    return 0;
}
